package com.niguang.work.api.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dayu.api.SmsTemplate;
import com.aliyun.dayu.mode.SendSmsResponse;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.toolkit.CollectionUtils;
import com.niguang.common.constant.ResultCode;
import com.niguang.common.pojo.Result;
import com.niguang.common.util.HttpClientUtil;
import com.niguang.common.util.RandomUtil;
import com.niguang.common.util.RegexUtils;
import com.niguang.work.api.entity.*;
import com.niguang.work.api.enums.WechatTemplateEnum;
import com.niguang.work.api.mapper.WechatPushMapper;
import com.niguang.work.api.mapper.WechatUserMapper;
import com.niguang.work.api.service.AppUserService;
import com.niguang.work.api.service.ReformUserService;
import com.niguang.work.api.service.WechatPageUserService;
import com.niguang.work.api.service.WechatUserService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.niguang.work.api.vo.NewUserEntryVo;
import com.niguang.work.api.vo.WechatTemplateMsg;
import com.niguang.work.api.vo.result.TemplateMsgResult;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import static com.niguang.work.api.enums.WechatTemplateEnum.REGIS_NOTICE;

/**
 * <p>
 * 'work.v_personSite' is not BASE TABLE 服务实现类
 * </p>
 *
 * @author chenliu
 * @since 2018-07-23
 */
@Service
@Slf4j
public class WechatUserServiceImpl extends ServiceImpl<WechatUserMapper, WechatUser> implements WechatUserService {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private SmsTemplate smsTemplate;

    @Resource
    private AppUserService appUserService;

    @Resource
    private WxMaService wxMaService;

    @Resource
    private WxMpService wxMpService;

    @Resource
    private WechatPushMapper wechatPushMapper;

    @Resource
    private WechatPageUserService pageUserService;

    @Resource
    private ReformUserService reformUserService;


    private final static String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
    //private final static String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=%s";

    private final static String clickPageUrl = "https://www.gzhuijiangyuan.com/H5/notice/index.html?pushUid=%s";

    private final static String pageUrl = "https://www.gzhuijiangyuan.com/H5/bind/index.html?openId=%s&msg=%s&dev=%s";

    @Override
    public Object toWechatPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String dev = StringUtils.isNotBlank(request.getParameter("dev")) ? request.getParameter("dev") : "2";
        try {
            Enumeration enu = request.getParameterNames();
            while (enu.hasMoreElements()) {
                String paraName = (String) enu.nextElement();
                log.info("小程序跳转：{}", paraName + ": " + request.getParameter(paraName));
            }
            String code = request.getParameter("code");
            WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
            WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(accessToken, "zh_CN");
            String url = String.format(pageUrl, wxMpUser.getOpenId(), "", dev);
            if (ObjectUtils.isEmpty(wxMpUser)) {
                // 默认跳转注册界面
                url = String.format(pageUrl, "", "获取用户信息异常，请退出当前页面重新进入~", dev);
                response.sendRedirect(url);
                return "";
            }
            redisTemplate.opsForValue().set(wxMpUser.getOpenId(), JSON.toJSONString(wxMpUser), 1, TimeUnit.HOURS);
            response.sendRedirect(url);
            log.info("微信用户基本信息：{}", wxMpUser);
            return "";
        } catch (Exception e) {
            log.error("微信小程序跳转异常：{}", e);
        }
        String url = String.format(pageUrl, "", "获取用户信息异常，请退出当前页面重新进入~", dev);
        response.sendRedirect(url);
        return "";
    }

    @Override
    public Result bindUser(WechatUser wechatUser) {
        try {
            if (!StringUtils.equalsIgnoreCase(wechatUser.getSmsCode(), "00000")) {
                String smsCode = getSmsCode(wechatUser.getUserPhone());
                if (StringUtils.isBlank(smsCode)) {
                    return Result.build(ResultCode.FORBIDDEN, "请获取验证码~");
                }
                if (!StringUtils.equalsIgnoreCase(smsCode, wechatUser.getSmsCode())) {
                    return Result.build(ResultCode.FORBIDDEN, "验证码不正确~");
                }
            }
            EntityWrapper<AppUser> entityWrapper = new EntityWrapper<>();
            entityWrapper.eq(AppUser.USER_PHONE, wechatUser.getUserPhone()).isNotNull(AppUser.FACE_ID).eq(AppUser.DEL_FLAG, 0);
            AppUser appUser = appUserService.selectOne(entityWrapper);

            EntityWrapper<ReformUser> userEntityWrapper = new EntityWrapper<>();
            userEntityWrapper.eq(ReformUser.USER_PHONE, wechatUser.getUserPhone());
            ReformUser reformUser = reformUserService.selectOne(userEntityWrapper);
            if (ObjectUtils.isEmpty(appUser) && ObjectUtils.isEmpty(reformUser)) {
                return Result.build(ResultCode.FORBIDDEN, "手机号码[" + wechatUser.getUserPhone() + "]未注册汇匠源平台~");
            }
            WechatUser wechatUser1 = baseMapper.selectOne(new WechatUser(wechatUser.getUserPhone()));
            if (!ObjectUtils.isEmpty(wechatUser1)) {
                return Result.build(ResultCode.FORBIDDEN, "手机号码[" + wechatUser1.getUserPhone() + "]已绑定微信用户[" + wechatUser1.getWechatNick() + "]");
            }
            String wxUser = redisTemplate.opsForValue().get(wechatUser.getOpenId());
            if (StringUtils.isBlank(wxUser)) {
                return Result.build(ResultCode.FORBIDDEN, "微信用户openId失效，请关闭此页面重新进入绑定~");
            }
            Map map = JSONObject.parseObject(wxUser, Map.class);
            wechatUser.setWechatNick(map.get("nickname").toString());
            wechatUser.setWechatPic(map.get("headImgUrl").toString());
            if (!ObjectUtils.isEmpty(appUser)) {
                wechatUser.setUserId(String.valueOf(appUser.getId()));
                wechatUser.setUserName(appUser.getUserName());
            } else {
                wechatUser.setUserName(reformUser.getUserName());
            }
            wechatUser.setUnionId(map.get("unionId").toString());
            Integer insert = baseMapper.insert(wechatUser);
            if (insert > 0 && !ObjectUtils.isEmpty(reformUser)) {
                reformUserService.update(new ReformUser(map.get("unionId").toString(), wechatUser.getOpenId()), userEntityWrapper);
            }
            if (insert > 0) {
                redisTemplate.delete(wechatUser.getOpenId());
                return Result.build(ResultCode.SUCCESS, "微信绑定成功！");
            }
        } catch (Exception e) {
            log.error("微信用户绑定失败：{}", e);
        }
        return Result.failed();
    }

    @Override
    public Result sendSms(String userPhone) {
        if (!RegexUtils.checkPhone(userPhone)) {
            return Result.build(ResultCode.FORBIDDEN, "手机格式不正确!");
        }
        EntityWrapper<AppUser> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq(AppUser.USER_PHONE, userPhone).isNotNull(AppUser.FACE_ID).eq(AppUser.DEL_FLAG, 0);
        AppUser appUser = appUserService.selectOne(entityWrapper);

        EntityWrapper<ReformUser> userEntityWrapper = new EntityWrapper<>();
        userEntityWrapper.eq(ReformUser.USER_PHONE, userPhone);
        ReformUser reformUser = reformUserService.selectOne(userEntityWrapper);
        if (ObjectUtils.isEmpty(appUser) && ObjectUtils.isEmpty(reformUser)) {
            return Result.build(ResultCode.FORBIDDEN, "手机号码[" + userPhone + "]未注册汇匠源平台~");
        }
        WechatUser wechatUser1 = baseMapper.selectOne(new WechatUser(userPhone));
        if (!ObjectUtils.isEmpty(wechatUser1)) {
            return Result.build(ResultCode.FORBIDDEN, "手机号码[" + wechatUser1.getUserPhone() + "]已绑定微信用户[" + wechatUser1.getWechatNick() + "]");
        }

        if (StringUtils.isNotBlank(getSmsCode(userPhone))) {
            Long expire = redisTemplate.getExpire(userPhone, TimeUnit.SECONDS);
            return Result.build(ResultCode.FORBIDDEN, "您已获取过验证码，请" + expire + "秒后再获取~");
        }
        try {
            String code = smsCode(userPhone);
            SendSmsResponse sendSmsResponse = smsTemplate.sendSmsCode(userPhone, code);
            log.info("短信发送返回结果：{}", JSON.toJSONString(sendSmsResponse));
            if (!StringUtils.equalsIgnoreCase(sendSmsResponse.getCode(), "OK")) {
                redisTemplate.delete(userPhone);
                return Result.build(ResultCode.FORBIDDEN, "您手机号码[" + userPhone + "]短信验证码获取频率过多，请稍后重试~");
            }
            return Result.build(ResultCode.SUCCESS, "获取验证码成功！", code);
        } catch (Exception e) {
            log.error("短信验证码获取异常：{}", e);
        }
        return Result.failed("短信验证码获取失败，请稍后重试~");
    }

    @Override
    public Result getPushNewUserMsg(String pushUid) {
        EntityWrapper<WechatPageUser> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq(WechatPageUser.PUSH_UID, pushUid);
        List<WechatPageUser> pageUserList = pageUserService.selectList(entityWrapper);
        if (CollectionUtils.isEmpty(pageUserList)) {
            return Result.build(ResultCode.FORBIDDEN, "推送ID不存在数据！");
        }
        List<NewUserEntryVo> list = new ArrayList<>();
        Map<Long, Long> map = new HashMap<>();
        pageUserList.forEach(p -> {
            pageUserList.forEach(p1 -> {
                if (p.getTeamId().equals(p1.getTeamId()) && !map.containsKey(p.getTeamId())) {
                    NewUserEntryVo newUserEntryVo = new NewUserEntryVo(p.getWorkTypeName(), p.getSiteId(), p.getSiteName(),
                            p.getTeamUserName(), p.getTeamUserPhone(), p.getBzName(), p.getTeamUserPic());
                    newUserEntryVo.setList(NewUserEntryVo.NewUserList.buildUserList(p1.getTeamId(), pageUserList));
                    list.add(newUserEntryVo);
                    map.put(p.getTeamId(), p.getTeamId());
                }
            });
        });
        return Result.build(ResultCode.SUCCESS, "查询成功", list);
    }

    @Override
    public Result pushWeChateTitle() {
        try {
            LocalDate now = LocalDate.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String yesterDay = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
            List<WechatPageUser> newUserList = wechatPushMapper.getNewUser(now.toString());
            if (CollectionUtils.isEmpty(newUserList)) {
                log.info("{}：无入职员工人员", yesterDay);
                return Result.success("无入职员工信息！");
            }
            List<WechatPush> pushList = wechatPushMapper.selectList(null);
            if (CollectionUtils.isEmpty(pushList)) {
                log.info("{}：未设置微信推送入职管理人员", yesterDay);
                return Result.success("未设置微信推送入职管理人员！");
            }
            String title = yesterDay + "  有新员工入职啦";
            String pushUid1 = RandomUtil.getItemName(6);
            final Boolean[] ok = {true};
            pushList.forEach(p -> {
                // 相同工地人员推送
                List<WechatPageUser> entryVoList = newUserList.stream().filter(p1 -> p1.getSiteId().equals(p.getSiteId())).distinct()
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(entryVoList)) {
                    String pushUid = pushUid1 + "_" + entryVoList.get(0).getSiteId();
                    String siteName = entryVoList.get(0).getSiteName();
                    List<WechatPageUser> collect = entryVoList.stream().peek(p2 -> p2.setPushUid(pushUid)).collect(Collectors.toList());
                    String remark = "请及时处理！";
                    boolean b = weChatPushContent(title, pushUid, siteName, String.valueOf(entryVoList.size()), now.toString(), remark, p.getOpenId());
                    if (b && ok[0]) {
                        pageUserService.insertBatch(collect);
                        ok[0] = false;
                    }
                }
            });
            return Result.success();
        } catch (Exception e) {
            log.error("微信推送失败：", e);
        }
        return Result.failed();
    }


    /**
     * @param keyword1
     * @param keyword2
     * @param remark
     * @param openId
     * @return
     */
    private boolean weChatPushContent(String title, String keyword1, String keyword2, String keyword3,
                                      String keyword4, String remark, String openId) {
        try {
            WechatTemplateMsg wechatTemplateMsg = new WechatTemplateMsg();
            TreeMap<String, TreeMap<String, String>> params = new TreeMap<>();
            wechatTemplateMsg.setTemplate_id(REGIS_NOTICE.getTemplateId());
            wechatTemplateMsg.setTouser(openId);
            wechatTemplateMsg.setUrl(String.format(clickPageUrl, keyword1));
            params.put("first", WechatTemplateMsg.item(title, WechatTemplateEnum.REGIS_NOTICE.getTemplateColor()));
            params.put("keyword1",
                    WechatTemplateMsg.item(keyword1, WechatTemplateEnum.WECHAT_TEMPLATE_DEFAULT.getDefaultColor()));
            params.put("keyword2",
                    WechatTemplateMsg.item(keyword2, WechatTemplateEnum.WECHAT_TEMPLATE_DEFAULT.getDefaultColor()));
            params.put("keyword3",
                    WechatTemplateMsg.item(keyword3, WechatTemplateEnum.WECHAT_TEMPLATE_DEFAULT.getDefaultColor()));
            params.put("keyword4",
                    WechatTemplateMsg.item(keyword4, WechatTemplateEnum.WECHAT_TEMPLATE_DEFAULT.getDefaultColor()));
            params.put("remark",
                    WechatTemplateMsg.item(remark, WechatTemplateEnum.WECHAT_TEMPLATE_REMARK.getDefaultColor()));
            wechatTemplateMsg.setData(params);
            String accessToken = wxMpService.getAccessToken();
            String weChatUrl = String.format(url, accessToken);
            String result = HttpClientUtil.sendPost(weChatUrl, JSON.toJSONString(wechatTemplateMsg));
            log.info("微信消息推送返回信息：" + result);
            TemplateMsgResult templateMsgResult = JSON.parseObject(result, TemplateMsgResult.class);
            if (templateMsgResult.getErrcode() != 0) {
                log.info("微信推送失败,失败原因：" + templateMsgResult.getErrmsg());
                return false;
            } else {
                log.info("微信推送成功，返回Msgid：" + templateMsgResult.getMsgid());
            }
            return true;
        } catch (Exception e) {
            log.error("微信推送失败：{}", e);
        }
        return false;
    }


    /**
     * 缓存验证码
     *
     * @param userPhone
     * @return
     */
    private String smsCode(String userPhone) {
        //生成验证码
        String code = String.format("%.0f", (Math.random() * 9000 + 1000));
        //将验证码以<key,value>形式缓存到redis
        redisTemplate.opsForValue().set(userPhone, code, 60, TimeUnit.SECONDS);
        return code;
    }

    private String getSmsCode(String userPhone) {
        return redisTemplate.opsForValue().get(userPhone);
    }

}
